//
//  AppleLoginManager.swift
//  LearningLanguage
//
//  Created by Rae on 2023/9/7.
//

import UIKit
import AuthenticationServices

public enum ResonseError {
    
    /// http请求报错
    case httpError(_ code: Int, _ description: String)
    
    /// 后端请求报错
    case customError(_ code: Int, _ description: String)
    
    /// 前端处理报错
    case clientError(_ code: Int, _ description: String)
    
    /// 错误码
    public var errorCode: Int {
        switch self {
        case .httpError(let code,_):
            return code
        case .customError(let code,_):
            return code
        case .clientError(let code,_):
            return code
        }
    }
    
    /// 错误描述
    public var errorDescripton: String {
        switch self {
        case .httpError(_, let description):
            return description
        case .customError(_, let description):
            return description
        case .clientError(_, let description):
            return description
        }
    }
    
}

public struct ResponseErrorInfo {
    
    /// 错误码
    public let errorCode: Int
    
    /// 错误信息描述
    public let errorDescripton: String
    
    /// 当前请求信息
    public let request: URLRequest?
    
    public init(_ error: ResonseError, _ request: URLRequest?) {
        self.errorCode = error.errorCode
        self.errorDescripton = error.errorDescripton
        self.request = request
    }

}

typealias AppleLoginToolSuccessClosures = (_ user: String, _ token: String) -> Void
typealias AppleLoginToolFailureClosures = (_ error: ResponseErrorInfo) -> Void

class AppleLoginTool: NSObject {
    
    static let instence = AppleLoginTool()
    
    private override init() {
        
    }
    
    override func copy() -> Any {
        return AppleLoginTool.instence // self
    }
    
    override func mutableCopy() -> Any {
        return AppleLoginTool.instence // self
    }
    
    private weak var parentController: UIViewController?
        
    private var successCompelecte: AppleLoginToolSuccessClosures?
    private var failureCompelecte: AppleLoginToolFailureClosures?
    
    public func isPast() -> Void {
        let provider = ASAuthorizationAppleIDProvider.init()
        provider.getCredentialState(forUserID: "") { (status, error) in
            switch status {
            case .revoked: do { // 已撤销
                
                }
            case .authorized: do {  // 已授权
                
                }
            case .notFound: do {    // 未发现
                
                }
            case .transferred: do { // 已转移
                
                }
            @unknown default:
                break
            }
        }
    }
    
    public func show(success: AppleLoginToolSuccessClosures? = nil, failure: AppleLoginToolFailureClosures? = nil) {
        successCompelecte = success
        failureCompelecte = failure
        let provider = ASAuthorizationAppleIDProvider.init()
        let request = provider.createRequest()
        let controller = ASAuthorizationController.init(authorizationRequests: [request])
        controller.delegate = self
        controller.presentationContextProvider = self
        controller.performRequests()
    }
    
}


@available(iOS 13, *)
extension AppleLoginTool: ASAuthorizationControllerPresentationContextProviding {
    func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
        return UIApplication.window ?? UIWindow()
    }
}

@available(iOS 13, *)
extension AppleLoginTool: ASAuthorizationControllerDelegate {
    
    func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
        var baseError: ResponseErrorInfo?
        switch error._code {
        case ASAuthorizationError.Code.canceled.rawValue:
            baseError = ResponseErrorInfo(.customError(0, "Cancel authorization!"), nil)
        case ASAuthorizationError.Code.failed.rawValue:
            baseError = ResponseErrorInfo(.customError(0, "Authorization request failed!"), nil)
        case ASAuthorizationError.Code.invalidResponse.rawValue:
            baseError = ResponseErrorInfo(.customError(0, "Invalid authorization request response!"), nil)
        case ASAuthorizationError.Code.notHandled.rawValue:
            baseError = ResponseErrorInfo(.customError(0, "Failed to process authorization request!"), nil)
        default:
            baseError = ResponseErrorInfo(.customError(0, "Privilege grant failed!"), nil)
        }
        guard let error = baseError, let closure = failureCompelecte else { return }
        closure(error)
    }
    
    func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
        if authorization.credential is ASAuthorizationAppleIDCredential {
            let credential = authorization.credential as! ASAuthorizationAppleIDCredential
            let user = credential.user
            guard let identityToken = credential.identityToken else {
                let baseError = ResponseErrorInfo(.customError(0, "identityToken is NULL"), nil)
                guard let closure = failureCompelecte else { return }
                closure(baseError)
                return
            }
            guard let token = String.init(data: identityToken, encoding: .utf8) else {
                let baseError = ResponseErrorInfo(.customError(0, "identityToken is NULL"), nil)
                guard let closure = failureCompelecte else { return }
                closure(baseError)
                return
            }
            guard let closure = successCompelecte else { return }
            closure(user, token)
        } else if authorization.credential is ASPasswordCredential {
            let baseError = ResponseErrorInfo(.customError(0, "Privilege grant failed!"), nil)
            guard let closure = failureCompelecte else { return }
            closure(baseError)
        } else {
            let baseError = ResponseErrorInfo(.customError(0, "Privilege grant failed!"), nil)
            guard let closure = failureCompelecte else { return }
            closure(baseError)
        }
    }
}
